iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
Rust

Rust 30 天養成計畫:從零到 CLI 專案系列 第 21

Day 21:錯誤處理進階與 panic! 的使用

  • 分享至 

  • xImage
  •  

1. 為什麼需要進階錯誤處理
昨天的小專案已經用過 Result 來避免程式崩潰,但那只是基本應用。今天我想更深入了解在不同錯誤情境下,該怎麼區分可恢復與不可恢復的情況。

2. panic!:當程式無法繼續執行時
panic! 會立即終止程式,並印出錯誤訊息與堆疊追蹤(stack trace)。

fn main() {
    let v = vec![1, 2, 3];
    println!("{}", v[99]); // 超出範圍
}

輸出:

thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:2:20
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

這種情況屬於程式邏輯錯誤(邏輯上應該不會發生,這類錯誤通常是開發階段就應該被修正的,不屬於使用者輸入錯誤),因此用 panic 結束是合理的。

3. 手動使用 panic!
當發現明顯錯誤時也能主動觸發 panic:

fn divide(a: i32, b: i32) -> i32 {
    if b == 0 {
        panic!("Cannot divide by zero!");
    }
    a / b
}

fn main() {
    divide(10, 0);
}

輸出:

thread 'main' panicked at 'Cannot divide by zero!', src/main.rs:3:9

4. Result 與 ? 運算子
Result<T, E> 是 Rust 中更常見的錯誤處理方式,用來代表「可能成功或失敗」。
? 可自動傳遞錯誤,讓程式更簡潔:

use std::fs::File;
use std::io::{self, Read};

fn read_file() -> Result<String, io::Error> {
    let mut file = File::open("text.txt")?; // 若錯誤,會自動 return Err(e)
    let mut content = String::new();
    file.read_to_string(&mut content)?;
    Ok(content)
}

fn main() {
    match read_file() {
        Ok(text) => println!("{}", text),
        Err(e) => println!("Error: {}", e),
    }
}

5. panic! vs Result:何時該用哪一種?
程式邏輯錯誤、無法恢復的情況(例如:除以 0、越界、程式錯誤) 則使用panic!
可預期錯誤、能讓使用者修正(例如:讀檔失敗、網路中斷) 則使用Result

6.學習心得與補充
今天的學習讓我更清楚地理解了 Rust 的錯誤處理邏輯。以前在寫 C++ 時,如果遇到除以零或開檔失敗的情況,通常只會回傳一個錯誤碼或直接當掉,但在 Rust 中,我必須明確選擇是用 Result 處理、還是直接用 panic! 結束,這讓我更主動地面對錯誤。尤其是 ? 運算子真的很好用,它讓錯誤傳遞的程式碼變得簡潔又清楚,整體看起來乾淨許多。


上一篇
Day 20:小專案— 字數統計工具
下一篇
Day 22:自訂錯誤型別與 Result 應用進階
系列文
Rust 30 天養成計畫:從零到 CLI 專案22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言